Option Explicit On 
Option Strict On

Imports TreeCreeper01Interfaces

' allows construction of proper list filters based on many criteria
' these can be utilized by business logig/GUI to simpilfy things a bit 

Public Class cListFilterCustomisation

    'Only for non-spatial filtering!
    Public Shared Function CreateNonSpatialListFilterForRandomSpecies(ByVal SpeciesList As ISpeciesAbundanceList, ByVal NumberOfSpeciesToInclude As Integer, ByVal UseAbundances As Boolean) As IListFilter

        Dim ResultingListFilter As IListFilter
        Dim SpeciesIndex As Integer
        Dim CandidateSpecies As Collection
        Dim CountOfSelectedSoFar As Integer
        Dim RandomIndex As Integer
        Dim Species As ISpeciesAbundance
        Dim RelativeAbundance As Double
        Dim ShouldBeAdded As Boolean
        Dim CurrentAbundanceSum As Double

        ResultingListFilter = New cListFilter("NonSpatialListFilterFor" & NumberOfSpeciesToInclude & "RandomSpecies")

        Select Case NumberOfSpeciesToInclude
            Case SpeciesList.CountOfSpecies
                'The number requested is the same as the current list, just fill with all and return
                With SpeciesList
                    For SpeciesIndex = 1 To .CountOfSpecies
                        With .SpeciesByIndexBaseOne(SpeciesIndex)
                            ResultingListFilter.AddListFilterItem(.UniqueKey, 1)
                        End With
                    Next
                End With
            Case Is > SpeciesList.CountOfSpecies
                'Exceptional case 
            Case Else
                'Then it's normal

                CandidateSpecies = New Collection
                With SpeciesList
                    For SpeciesIndex = 1 To .CountOfSpecies
                        CandidateSpecies.Add(.SpeciesByIndexBaseOne(SpeciesIndex))
                        CurrentAbundanceSum = CurrentAbundanceSum + .SpeciesByIndexBaseOne(SpeciesIndex).Abundance
                    Next
                End With

                CountOfSelectedSoFar = 0
                Do While CountOfSelectedSoFar < NumberOfSpeciesToInclude
                    RandomIndex = cRandomGenerator.NextRandom(1, CandidateSpecies.Count)
                    Species = CType(CandidateSpecies(RandomIndex), ISpeciesAbundance)
                    ShouldBeAdded = False
                    If UseAbundances Then
                        RelativeAbundance = Species.Abundance / CurrentAbundanceSum
                        If cRandomGenerator.NextRandomBetweenZeroAndOne < RelativeAbundance Then
                            ShouldBeAdded = True
                        End If
                    Else
                        ShouldBeAdded = True
                    End If
                    If ShouldBeAdded Then
                        ResultingListFilter.AddListFilterItem(Species.UniqueKey, 1)
                        CurrentAbundanceSum = CurrentAbundanceSum - Species.Abundance
                        '
                        CandidateSpecies.Remove(RandomIndex)
                        CountOfSelectedSoFar = CountOfSelectedSoFar + 1
                    End If
                Loop

        End Select

        Return ResultingListFilter

    End Function


    ' NOTE: there must be at least one species not yet defined in the filter, otherwise we get infinite loop
    ' TO BE DONE: Maybe this could be done better
    Private Shared Sub AddRandomSpeciesFilterItemNotYetAdded(ByVal ListFilter As IListFilter, ByVal SpeciesList As ISpeciesAbundanceList)

        Dim AdditionCompleted As Boolean
        Dim SpeciesCount As Integer
        Dim TaxonomicSpecies As ITaxonomicSpecies
        Dim RandomIndex As Integer
        Dim ListFilterItemExisting As IListFilterItem

        SpeciesCount = SpeciesList.CountOfSpecies

        While Not AdditionCompleted
            RandomIndex = cRandomGenerator.NextRandom(1, SpeciesCount)
            TaxonomicSpecies = SpeciesList.SpeciesByIndexBaseOne(RandomIndex).TaxonomicSpecies
            ListFilterItemExisting = ListFilter.ListFilterItemByUniqueName(TaxonomicSpecies.UniqueKey)
            If ListFilterItemExisting Is Nothing Then
                ' we can add this!
                ListFilter.AddListFilterItem(TaxonomicSpecies.UniqueKey, 1)
                AdditionCompleted = True
            End If

        End While


    End Sub


End Class

